//
//  ViewController.m
//  TEST_NSURLProtocol
//
//  Created by lianglibao on 2019/3/11.
//  Copyright © 2019年 lianglibao. All rights reserved.
//

#import "ViewController.h"
#import <WebKit/WebKit.h>
#import <arpa/inet.h>
#import <resolv.h>
#import <netdb.h>

@interface ViewController ()<UIWebViewDelegate, WKNavigationDelegate>
@property (nonatomic, strong) UIWebView *webView;
@property (nonatomic, strong) WKWebView *wkWebView;

@end

@implementation ViewController
// MARK: - TEST NSURLProtocol intercept UIWebView and WKWebView
- (UIWebView *)webView {
	if (!_webView) {
		_webView = [[UIWebView alloc] initWithFrame:self.view.bounds];
		_webView.delegate = self;
		[self.view addSubview:_webView];
	}
	return _webView;
}

- (WKWebView *)wkWebView {
	if (!_wkWebView) {
		_wkWebView = [[WKWebView alloc] initWithFrame:self.view.frame];
		_wkWebView.navigationDelegate = self;
		Class cls = NSClassFromString(@"WKBrowsingContextController");
		SEL sel = NSSelectorFromString(@"registerSchemeForCustomProtocol:");
		if ([cls respondsToSelector:sel]) {
			// 通过http和https的请求，同理可通过其他的Scheme 但是要满足ULR Loading System
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Warc-performSelector-leaks"
			[cls performSelector:sel withObject:@"https" withObject:@"http"];
#pragma clang diagnostic pop
		}
		[self.view addSubview:_wkWebView];
	}
	return _wkWebView;
}


- (void)viewDidLoad {
	[super viewDidLoad];
	// Do any additional setup after loading the view, typically from a nib.
	
}

- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
	NSURL *url = [[NSURL alloc] initWithString:@"https://sina.cn"];
	NSURLRequest *request = [NSURLRequest requestWithURL:url];
	[self.wkWebView loadRequest:request];
}


// MARK: - UIWebViewDelegate
- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType {
	return YES;
}

- (void)webViewDidStartLoad:(UIWebView *)webView {
	
}

- (void)webViewDidFinishLoad:(UIWebView *)webView {
	
}
- (void)webView:(UIWebView *)webView didFailLoadWithError:(NSError *)error {
	
}

// MARK: - WKWebViewDelegate

/*! @abstract Decides whether to allow or cancel a navigation.
 @param webView The web view invoking the delegate method.
 @param navigationAction Descriptive information about the action
 triggering the navigation request.
 @param decisionHandler The decision handler to call to allow or cancel the
 navigation. The argument is one of the constants of the enumerated type WKNavigationActionPolicy.
 @discussion If you do not implement this method, the web view will load the request or, if appropriate, forward it to another application.
 */
- (void)webView:(WKWebView *)webView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler {
	decisionHandler(WKNavigationActionPolicyAllow);
}

/*! @abstract Invoked when a main frame navigation starts.
 @param webView The web view invoking the delegate method.
 @param navigation The navigation.
 */
- (void)webView:(WKWebView *)webView didStartProvisionalNavigation:(null_unspecified WKNavigation *)navigation {
	
}

/*! @abstract Invoked when a server redirect is received for the main
 frame.
 @param webView The web view invoking the delegate method.
 @param navigation The navigation.
 */
- (void)webView:(WKWebView *)webView didReceiveServerRedirectForProvisionalNavigation:(null_unspecified WKNavigation *)navigation {
	
}

/*! @abstract Invoked when an error occurs while starting to load data for
 the main frame.
 @param webView The web view invoking the delegate method.
 @param navigation The navigation.
 @param error The error that occurred.
 */
- (void)webView:(WKWebView *)webView didFailProvisionalNavigation:(null_unspecified WKNavigation *)navigation withError:(NSError *)error {
	
}

/*! @abstract Invoked when content starts arriving for the main frame.
 @param webView The web view invoking the delegate method.
 @param navigation The navigation.
 */
- (void)webView:(WKWebView *)webView didCommitNavigation:(null_unspecified WKNavigation *)navigation {
	
}

/*! @abstract Invoked when a main frame navigation completes.
 @param webView The web view invoking the delegate method.
 @param navigation The navigation.
 */
- (void)webView:(WKWebView *)webView didFinishNavigation:(null_unspecified WKNavigation *)navigation {
	
}

/*! @abstract Invoked when an error occurs during a committed main frame
 navigation.
 @param webView The web view invoking the delegate method.
 @param navigation The navigation.
 @param error The error that occurred.
 */
- (void)webView:(WKWebView *)webView didFailNavigation:(null_unspecified WKNavigation *)navigation withError:(NSError *)error {
	
}


/*! @abstract Invoked when the web view's web content process is terminated.
 @param webView The web view whose underlying web content process was terminated.
 */
- (void)webViewWebContentProcessDidTerminate:(WKWebView *)webView {
	
}

// MARK: - TEST DNS analysis method type
- (void)localDNS1 {
	CFAbsoluteTime start = CFAbsoluteTimeGetCurrent();
	unsigned char auResult[512];
	int nBytesRead = 0;
	
	nBytesRead = res_query("api.abctime.com", ns_c_in, ns_t_a, auResult, sizeof(auResult));
	
	ns_msg handle;
	ns_initparse(auResult, nBytesRead, &handle);
	
	NSMutableArray *ipList = nil;
	int msg_count = ns_msg_count(handle, ns_s_an);
	if (msg_count > 0) {
		ipList = [[NSMutableArray alloc] initWithCapacity:msg_count];
		for(int rrnum = 0; rrnum < msg_count; rrnum++) {
			ns_rr rr;
			if(ns_parserr(&handle, ns_s_an, rrnum, &rr) == 0) {
				char ip1[16];
				strcpy(ip1, inet_ntoa(*(struct in_addr *)ns_rr_rdata(rr)));
				NSString *ipString = [[NSString alloc] initWithCString:ip1 encoding:NSASCIIStringEncoding];
				if (![ipString isEqualToString:@""]) {
					
					//将提取到的IP地址放到数组中
					[ipList addObject:ipString];
				}
			}
		}
		CFAbsoluteTime end = CFAbsoluteTimeGetCurrent();
		NSLog(@"11111 === ip === %@ === time cost: %0.3fs", ipList,end - start);
	}
}

- (void)localDNS2 {
	CFAbsoluteTime start = CFAbsoluteTimeGetCurrent();
	char   *ptr, **pptr;
	struct hostent *hptr;
	char   str[32];
	ptr = "api.abctime.com";
	NSMutableArray * ips = [NSMutableArray array];
	
	if((hptr = gethostbyname(ptr)) == NULL)
	{
		printf("no ips %s", ptr);
		return;
	}
	
	printf("official hostname:%s\n",hptr->h_name);
	for(pptr = hptr->h_aliases; *pptr != NULL; pptr++)
		printf(" alias hostname:%s\n",*pptr);
	
	switch(hptr->h_addrtype)
	{
		case AF_INET:
		case AF_INET6:
			for(pptr=hptr->h_addr_list; *pptr!=NULL; pptr++) {
				NSString * ipStr = [NSString stringWithCString:inet_ntop(hptr->h_addrtype, *pptr, str, sizeof(str)) encoding:NSUTF8StringEncoding];
				[ips addObject:ipStr?:@""];
			}
			//                printf(" address:%s\n", inet_ntop(hptr->h_addrtype, *pptr, str, sizeof(str)));
			//            printf(" first address: %s\n",inet_ntop(hptr->h_addrtype, hptr->h_addr, str, sizeof(str)));
			break;
		default:
			//            printf("unknown address type\n");
			break;
	}
	CFAbsoluteTime end = CFAbsoluteTimeGetCurrent();
	NSLog(@"22222 === ip === %@ === time cost: %0.3fs", ips,end - start);
}

- (void)localDNS3 {
	
	Boolean result,bResolved;
	CFHostRef hostRef;
	CFArrayRef addresses = NULL;
	NSMutableArray * ipsArr = [[NSMutableArray alloc] init];
	CFStringRef hostNameRef = CFStringCreateWithCString(kCFAllocatorDefault, "api.abctime.com", kCFStringEncodingASCII);
	
	hostRef = CFHostCreateWithName(kCFAllocatorDefault, hostNameRef);
	CFAbsoluteTime start = CFAbsoluteTimeGetCurrent();
	result = CFHostStartInfoResolution(hostRef, kCFHostAddresses, NULL);
	if (result == TRUE) {
		addresses = CFHostGetAddressing(hostRef, &result);
	}
	bResolved = result == TRUE ? true : false;
	
	if(bResolved)
	{
		struct sockaddr_in* remoteAddr;
		for(int i = 0; i < CFArrayGetCount(addresses); i++)
		{
			CFDataRef saData = (CFDataRef)CFArrayGetValueAtIndex(addresses, i);
			remoteAddr = (struct sockaddr_in*)CFDataGetBytePtr(saData);
			
			if(remoteAddr != NULL)
			{
				//获取IP地址
				char ip[16];
				strcpy(ip, inet_ntoa(remoteAddr->sin_addr));
				NSString * ipStr = [NSString stringWithCString:ip encoding:NSUTF8StringEncoding];
				[ipsArr addObject:ipStr];
			}
		}
	}
	CFAbsoluteTime end = CFAbsoluteTimeGetCurrent();
	NSLog(@"33333 === ip === %@ === time cost: %0.3fs", ipsArr,end - start);
	CFRelease(hostNameRef);
	CFRelease(hostRef);
}

@end
